using System;
using System.ComponentModel;

namespace InfiniTec.Exchange.Notifications
{
	public class EventInfo
	{
		public EventInfo(EventType eventType, EventCategory eventCategory, string watermark, DateTime timestamp, FolderReference parentFolderId): this(watermark)
		{
			if (parentFolderId == null) throw new ArgumentNullException("parentFolderId");
			if (!Enum<EventType>.IsDefined(eventType) || eventType == EventType.None)
				throw new InvalidEnumArgumentException("eventType", (int) eventType, typeof (EventType));
			if (!Enum<EventCategory>.IsDefined(eventCategory) || eventCategory == EventCategory.None)
				throw new InvalidEnumArgumentException("eventCategory", (int) eventCategory, typeof (EventCategory));

			EventType = eventType;
			Timestamp = timestamp;
			ParentFolderId = parentFolderId;
			EventCategory = eventCategory;
		}

		private EventInfo(string watermark)
		{
			if (string.IsNullOrEmpty(watermark)) throw new ArgumentNullException("watermark");
			Watermark = watermark;
		}

		public FolderReference FolderId { get; private set; }
		public EventType EventType { get; private set; }
		public FolderReference ParentFolderId { get; private set; }
		public FolderReference OldParentFolderId { get; private set; }
		public ItemReference ItemId { get; private set; }
		public ItemReference OldItemId { get; private set; }
		public string Watermark { get; private set; }
		public DateTime Timestamp { get; private set; }
		public EventCategory EventCategory { get; private set; }
		public int? UnreadCount { get; private set; }

		public static EventInfo ForCopyOrMoveEvent(EventType eventType, FolderReference parentFolderId, ItemReference itemId,
		                                           FolderReference oldParentFolderId, ItemReference oldItemId, DateTime timestamp, string watermark)
		{
			if (parentFolderId == null) throw new ArgumentNullException("parentFolderId");
			if (itemId == null) throw new ArgumentNullException("itemId");
			if (oldParentFolderId == null) throw new ArgumentNullException("oldParentFolderId");
			if (oldItemId == null) throw new ArgumentNullException("oldItemId");
			if (eventType != EventType.Copied && eventType != EventType.Moved)
				throw new InvalidEnumArgumentException("eventType", (int) eventType, typeof (EventType));

			return new EventInfo(eventType, EventCategory.ItemEvent, watermark, timestamp, parentFolderId)
			       {
			       ItemId = itemId,
			       OldParentFolderId = oldParentFolderId,
			       OldItemId = oldItemId,
			       };
		}

		public static EventInfo ForModifiedEvent(FolderReference parentFolderId, ItemReference itemId, DateTime timeStamp, string watermark)
		{
			if (itemId == null) throw new ArgumentNullException("itemId");
			return new EventInfo(EventType.Modified, EventCategory.ItemEvent, watermark, timeStamp, parentFolderId)
			       {
			       ItemId = itemId,
			       };
		}

		public static EventInfo ForModifiedEvent(FolderReference parentFolderId, FolderReference folderId, DateTime timeStamp, int? unreadCount,
		                                         string watermark)
		{
			return new EventInfo(EventType.Modified, EventCategory.FolderEvent, watermark, timeStamp, parentFolderId)
			       {
			       FolderId = folderId,
			       UnreadCount = unreadCount
			       };
		}

		public static EventInfo ForNewOrDeletionEvent(EventType eventType, FolderReference parentFolderId, ItemReference itemId, DateTime timeStamp,
		                                              string watermark)
		{
			if (string.IsNullOrEmpty(watermark)) throw new ArgumentNullException("watermark");
			if (parentFolderId == null) throw new ArgumentNullException("parentFolderId");
			if (eventType != EventType.Deleted && eventType != EventType.Created && eventType != EventType.NewMail)
			{
				throw new InvalidEnumArgumentException("eventType", (int) eventType, typeof (EventType));
			}
			return new EventInfo(eventType, EventCategory.ItemEvent, watermark, timeStamp, parentFolderId)
			       {
			       ItemId = itemId,
			       };
		}

		public static EventInfo ForStatusEvent(string watermark)
		{
			if (string.IsNullOrEmpty(watermark)) throw new ArgumentNullException("watermark");
			return new EventInfo(watermark)
				   {
					   EventCategory = EventCategory.None,
					   EventType = EventType.Status
				   };
		}
	}
}